<?php

/**
 * Captcha 3D
 */
class Captcha3D extends Plugin_Object {

	protected $hypot = 6;

	protected $image = NULL;

	/**
	 * Constructor
	 */
	public function __construct() {
		parent::__construct();
	}

	/**
	 * Fetch proection
	 * @param number $x1
	 * @param number $y1
	 * @param number $z1
	 * @return array
	 */
	private function get_proection($x1,$y1,$z1)   {
		$x = $x1 * $this->hypot;
		$y = $z1 * $this->hypot;
		$z = -$y1 * $this->hypot;

		$xx = 0.707106781187;
		$xy = 0;
		$xz = -0.707106781187;

		$yx = 0.408248290464;
		$yy = 0.816496580928;
		$yz = 0.408248290464;

		$cx = $xx*$x + $xy*$y + $xz*$z;
		$cy = $yx*$x + $yy*$y + $yz*$z+ 20 * $this->hypot;
		return array(
			'x' => $cx,
			'y' => $cy
		);
	}

	/**
	 * Calculate Z-axis
	 * @param number $x
	 * @param number $y
	 * @return number
	 */
	private function z_function($x,$y) {
		$z = imagecolorat($this->image,$y/2,$x/2)>0?2.6:0;
		if( $z != 0 ){
			$z += mt_rand(0,60)/100;
		}
		$z += 1.4 * sin(($x+$this->startX)*M_PI/15)*sin(($y+$this->startY)*M_PI/15);
		return $z;
	}

	/**
	 * Render an image
	 * @param string $code
	 */
	public function render($code) {
		$xx = 30;
		$yy = 60;

		$this->image = imagecreatetruecolor($yy * $this->hypot, $xx * $this->hypot);

		$whiteColor = imagecolorallocate($this->image,255,255,255);
		imagefilledrectangle($this->image,0,0,$yy * $this->hypot, $xx * $this->hypot,$whiteColor);

		$textColor = imagecolorallocate($this->image,0,0,0);
		imagestring($this->image, 5, 3, 0, $code, $textColor);

		$this->startX = mt_rand(0,$xx);
		$this->startY = mt_rand(0,$yy);

		$coordinates = array();

		for($x = 0; $x < $xx + 1; $x++){
			for($y = 0; $y < $yy + 1; $y++){
				$coordinates[$x][$y] = $this->get_proection($x,$y,$this->z_function($x,$y));
			}
		}

		for($x = 0; $x < $xx; $x++){
			for($y = 0; $y < $yy; $y++){
				$coord = array();
				$coord[] = $coordinates[$x][$y]['x'];
				$coord[] = $coordinates[$x][$y]['y'];

				$coord[] = $coordinates[$x+1][$y]['x'];
				$coord[] = $coordinates[$x+1][$y]['y'];

				$coord[] = $coordinates[$x+1][$y+1]['x'];
				$coord[] = $coordinates[$x+1][$y+1]['y'];

				$coord[] = $coordinates[$x][$y+1]['x'];
				$coord[] = $coordinates[$x][$y+1]['y'];

				$c = (int) ($this->z_function($x,$y)*32);
				$linesColor = imagecolorallocate($this->image, $c, $c, $c);
				imagefilledpolygon($this->image, $coord, 4, $whiteColor);
				imagepolygon($this->image, $coord, 4, $linesColor);
			}
		}

		imagestring($this->image, 5, 3, 0, $code, $whiteColor);

		// set HTTP headers
		$http = &platcode()->plugins->import('HTTP');

		$http->set_header('Cache-Control', 'no-cache');
		$http->set_header('Pragma', 'no-cache');
		$http->set_header('Content-Type', 'image/png');

		// output an image
		imagepng($this->image);
		imagedestroy($this->image);
	}
}